#define _CRT_SECURE_NO_WARNINGS 1

#include "game.h"

void InitBoard(char arr[ROWS][COLS], int rows, int cols, char set)
{
	int i = 0;
	for (i = 0; i < rows; i++)
	{
		int j = 0;
		for (j = 0; j < cols; j++)
		{
			arr[i][j] = set;
		}
	}
}

void DisplayBoard(char arr[ROWS][COLS], int row, int col)
{
	int i = 0;
	printf("------扫雷游戏------\n");
	//打印列号
	for (i = 0; i <= col; i++)
	{
		printf("%d ", i);
	}
	printf("\n");

	for (i = 1; i <= row; i++)
	{
		int j = 0;
		printf("%d ", i);
		for (j = 1; j <= col; j++)
		{
			printf("%c ", arr[i][j]);
		}
		printf("\n");
	}
}

void SetMine(char arr[ROWS][COLS], int row, int col)
{
	int count = EASY_COUNT;
	while (count)
	{
		int x = rand() % row + 1;
		int y = rand() % col + 1;
		if (arr[x][y] == '0')
		{
			arr[x][y] = '1';
			count--;
		}
	}
}

// 确认该点非雷后，统计周围八个点雷的数量
static int GetMineCount(char mine[ROWS][COLS], int x, int y)
{
	int i = 0;
	int count = 0;
	for (i = x - 1; i <= x + 1; i++)
	{
		int j = 0;
		for (j = y - 1; j <= y + 1; j++)
		{
			if (i == x && j == y) continue; // 跳过自身
			count += (mine[i][j] - '0');
		}
	}
	return count;
}

int dx[] = { -1, 0, 1, 1, 1, 0, -1, -1 };
int dy[] = { -1, -1, -1, 0, 1, 1, 1, 0 };
// 展开
static void Spread(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y)
{
	if (x < 1 || x > ROW || y < 1 || y > COL) {
		return;
	}
	int count = GetMineCount(mine, x, y);
	if (!count)
	{
		if (show[x][y] != '*' && show[x][y] != '@') {
			return;
		}

		show[x][y] = ' ';

		for (int i = 0; i < 8; i++) {
			int newX = x + dx[i];
			int newY = y + dy[i];

			Spread(mine, show, newX, newY);
		}
	}
	else show[x][y] = count + '0';
}

static bool TestMine(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y)
{
	if (mine[x][y] == '1')
	{
		show[x][y] = '!';
		printf("你被炸死了，游戏结束！\n");
		DisplayBoard(show, ROW, COL);

		return false;
	}
	else if (mine[x][y] == '0')
	{
		Spread(mine, show, x, y);
	}
	DisplayBoard(show, ROW, COL);

	return true;
}

static void Mark(char show[ROWS][COLS], int x, int y)
{
	if (show[x][y] == '*') {
		show[x][y] = '@';
		DisplayBoard(show, ROW, COL);
	}
	else printf("该点不该标记，请重新选点\n");
}

static void DelMark(char show[ROWS][COLS], int x, int y)
{
	if (show[x][y] == '@') {
		show[x][y] = '*';
		DisplayBoard(show, ROW, COL);
	}
	else printf("该点不会被取消标记，请重新选点\n");
}

static bool Choose(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y)
{
	printf("1.排雷\n");
	printf("2.标记\n");
	printf("3.取消标记\n");
	printf("请选择:>");

	int select, ret = true;
	scanf("%d", &select);

	switch (select)
	{
	case 1:
		ret = TestMine(mine, show, x, y);
		break;
	case 2:
		Mark(show, x, y);
		break;
	case 3:
		DelMark(show, x, y);
		break;
	default: printf("非法操作，请重新输入\n");
	}

	return ret;
}

void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS])
{
	int x = 0, y = 0;
	int star = EASY_COUNT + 1; // 多个1，刚好能进入循环

	while (star > EASY_COUNT)
	{
		printf("请输入行列:> ");
		scanf("%d %d", &x, &y);

		if (x >= 1 && x <= ROW && y >= 1 && y <= COL)
		{
			if (!Choose(mine, show, x, y))
				break;

			star = 0;
			for (int i = 1; i <= ROW; i++) {
				for (int j = 1; j <= COL; j++) {
					if (show[i][j] == '*' || show[i][j] == '@') star++;
				}
			}
		}
		else printf("非法坐标,请重新输入\n");

		if (star == EASY_COUNT) {
			printf("游戏结束，你通关了!\n");
		}
	}
}